package com.cskaoyan.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author stone
 * @date 2021/11/19 17:09
 */
@Aspect
@Component
public class CustomAspect {

    //使用@Pointcut的value属性作为切入点的表达式
    @Pointcut("execution(* com..service..*(..))")
    public void servicePointcut() { //方法名是作为id进行使用的
    }

    //通知注解的value属性；
    //   1、直接写切入点表达式
    //   2、引用切入点方法 👉 有一对括号
    @Before("servicePointcut()")
    public void beforeTarget(JoinPoint joinPoint) {
        //代理对象
        Object proxy = joinPoint.getThis();
        //委托类对象
        Object target = joinPoint.getTarget();

        //之前拿到的是Method
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String name = signature.getName();
        Method method = signature.getMethod();

        Object[] args = joinPoint.getArgs();

        System.out.println("委托类方法执行之前");
    }

    @After("servicePointcut()")
    public void after() {
        System.out.println("在委托类方法执行之后");
    }

    @Around("execution(* com..service..*(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        String name = joinPoint.getSignature().getName();
        if ("buy".equals(name) && args.length == 2) {
            args[1] = 10;
        }
        System.out.println("around的前半部分");
        //要能够执行到委托类的方法
        Object proceed = joinPoint.proceed(args);

        System.out.println("around的后半部分");
        return proceed;
    }

    @AfterReturning(value = "servicePointcut()",returning = "result")
    public void afterReturning(Object result) {
        System.out.println("AfterReturning通知:" + result);
    }

    //可以使用Exception或Throwable
    @AfterThrowing(value = "servicePointcut()",throwing = "exception")
    public void afterThrowing(Exception exception) {
        System.out.println("AfterThrowing通知：" + exception.getMessage());
    }
}
